/****************************************\
|* MFZPSP LLE PSP Emulator              *|
|* Copyright (c) 2008 Mauro Frischherz  *|
|* See License.txt for details          *|
\****************************************/

#include "corewrapper.h"

#include "core/cpu.h"
#include "core/memory.h"
#include "core/gpu.h"
#include "core/loader.h"

#include "tools/log.h"
#include "tools/functions.h"

#include <stdio.h>


/* PSP Functions */

bool PSPInit() // Inits PSP and tests cpu
{
	ResetMemory();
	ResetLoader();
	ResetCPU();
	printevent("Init PSP");
	return true;
}

bool PSPReset() // Resets CPU, clears memory and registers
{
	printevent("Reset PSP");
	StopCPU();
	PSPInit();
	return true;
}

bool PSPStart() // Starts CPU, will not run unless valid rom is loaded
{
	printevent("Start PSP");
	if(GetLoaded())
	{
		RunCPU();
		return true;
	}
	else
	{
		printerror("No File Loaded");
		return false;
	}
}

bool PSPPause() // Pauses CPU
{
	if(GetCPUState() == CPU_STATE_RUNNING)
	{
		printevent("Pause PSP");
		PauseCPU();
	}
	else
	{
		printerror("Cannot pause CPU. CPU not running");
	}
	return true;
}

bool PSPResume() // Resumes CPU-Operation
{
	printevent("Resume PSP");
	RunCPU();
	return true;
}

bool PSPSingleStep()
{
	if(GetLoaded())
	{
		if(SingleStep())
			return true;
		else
			return false;
	}
	else
	{
		printerror("No File Loaded");
		return false;
	}
}


/* Loading ROMs */

bool LoadFile(char* path) // Does all the loading and initialisation needed
{
	ResetMemory();
	int FileType = GetFileType(path);
	
	if(FileType != FILE_TYPE_NULL)
	{
		if(LoadAndDecodeFile(path, FileType))
			return true;
		else
			return false;
	}
	else
	{
		printerror("Invalid extension");
		return false;
	}
}

/* Debugging Stuff / Disasm */
uint GetProgramCounter()
{
	return GetPC();
}

uint GetCPURegister(int index) // Returns Integer to CPU-Registers array
{
	return GetReg(index);
}

void GetCPURegisterText(int index, char* dest) // Return CPU-Register as string
{
	sprintf(dest, "0x%08X", GetReg(index));
}

void GetCPUCode(uint pc, char* pclist, char* operation, char* opcode, char* comment)
{
	sprintf(pclist, "%08X", pc);
	sprintf(operation, "XXXXXXXX");	
	sprintf(opcode, "%08X", GetOp(pc));	
	sprintf(comment,"%s", (pc == GetEntry()) ? "Entry Point" : "XXXXXXXX");
}

void MemDump(uint address, char* hexdump, char* asciidump, int mode)
{
	switch(mode)
	{
	case MEM_DUMP_MODE_8:
		sprintf(hexdump, "%02X %02X %02X %02X %02X %02X %02X %02X",
				uRead8(address + 0), 
				uRead8(address + 1), 
				uRead8(address + 2), 
				uRead8(address + 3), 
				uRead8(address + 4), 
				uRead8(address + 5), 
				uRead8(address + 6), 
				uRead8(address + 7));
		sprintf(asciidump, "%c%c%c%c%c%c%c%c",
				(uRead8(address + 0) < 0x20) ? '.' : uRead8(address + 0), 
				(uRead8(address + 1) < 0x20) ? '.' : uRead8(address + 1), 
				(uRead8(address + 2) < 0x20) ? '.' : uRead8(address + 2), 
				(uRead8(address + 3) < 0x20) ? '.' : uRead8(address + 3), 
				(uRead8(address + 4) < 0x20) ? '.' : uRead8(address + 4), 
				(uRead8(address + 5) < 0x20) ? '.' : uRead8(address + 5), 
				(uRead8(address + 6) < 0x20) ? '.' : uRead8(address + 6), 
				(uRead8(address + 7) < 0x20) ? '.' : uRead8(address + 7));
		break;
	case MEM_DUMP_MODE_16:
		sprintf(hexdump, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
				uRead8(address + 0), 
				uRead8(address + 1), 
				uRead8(address + 2), 
				uRead8(address + 3), 
				uRead8(address + 4), 
				uRead8(address + 5), 
				uRead8(address + 6), 
				uRead8(address + 7),
				uRead8(address + 8), 
				uRead8(address + 9), 
				uRead8(address + 10), 
				uRead8(address + 11), 
				uRead8(address + 12), 
				uRead8(address + 13), 
				uRead8(address + 14),
				uRead8(address + 15));
		sprintf(asciidump, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
				(uRead8(address + 0) < 0x20)  ? '.' : uRead8(address + 0), 
				(uRead8(address + 1) < 0x20)  ? '.' : uRead8(address + 1), 
				(uRead8(address + 2) < 0x20)  ? '.' : uRead8(address + 2), 
				(uRead8(address + 3) < 0x20)  ? '.' : uRead8(address + 3), 
				(uRead8(address + 4) < 0x20)  ? '.' : uRead8(address + 4), 
				(uRead8(address + 5) < 0x20)  ? '.' : uRead8(address + 5), 
				(uRead8(address + 6) < 0x20)  ? '.' : uRead8(address + 6), 
				(uRead8(address + 7) < 0x20)  ? '.' : uRead8(address + 7),
				(uRead8(address + 8) < 0x20)  ? '.' : uRead8(address + 8), 
				(uRead8(address + 9) < 0x20)  ? '.' : uRead8(address + 9), 
				(uRead8(address + 10) < 0x20) ? '.' : uRead8(address + 10), 
				(uRead8(address + 11) < 0x20) ? '.' : uRead8(address + 11), 
				(uRead8(address + 12) < 0x20) ? '.' : uRead8(address + 12), 
				(uRead8(address + 13) < 0x20) ? '.' : uRead8(address + 13), 
				(uRead8(address + 14) < 0x20) ? '.' : uRead8(address + 14), 
				(uRead8(address + 15) < 0x20) ? '.' : uRead8(address + 15));
		break;
	default:
		break;
	}
}

uint GetBase()
{
	return 0x08900000;
}
